package com.jufa_3.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.jufa_3.common.R;
import com.jufa_3.common.WeiChat;
import com.jufa_3.dto.PayInfo;
import com.jufa_3.entity.ComboOrder;
import com.jufa_3.entity.PayOrder;
import com.jufa_3.mapper.ComboOrderMapper;
import com.jufa_3.service.PayOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/pay")
public class PayController {

    @Autowired
    private PayOrderService payOrderService;

    @Autowired
    private ComboOrderMapper comboOrderMapper;

    /**
     * 统一支付
     */
    @GetMapping("/placeAnOrder")
    public R<Map<String, String>> placeAnOrder(PayInfo payInfo, String moreInfo) {
        try {
            // 支付的业务逻辑
            Map<String, String> payReturnInfo = WeiChat.payment(payInfo);
            if (payReturnInfo != null) {
                // 增加未支付订单
                Float fee = payInfo.getTotal_fee().floatValue() / 100;
                PayOrder payorder = new PayOrder(payInfo.getOut_trade_no(), payInfo.getOpenid(), payInfo.getBody(),
                        fee, "NOTPAY", LocalDateTime.now(), moreInfo);
                if (!payOrderService.save(payorder)) {
                    log.warn("待支付订单" + payorder + "未入库");
                }
                // 业务逻辑结束 回传给小程序端唤起支付
                return R.success(payReturnInfo);
            } else {
                return R.error(4005, "统一下单失败，参数有误");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(4004, "统一下单失败，程序异常");
        }
    }

    /**
     * 微信支付回调函数
     */
    @PostMapping(value = "/callback")
    public void wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, String> map = WeiChat.notifyDecode(request);
        String resXml;
        String returnCode = map.get("return_code");
        if ("SUCCESS".equals(returnCode)) {                 //通信成功
            // 验证签名是否正确
            boolean verifySign = WeiChat.verifySign(map);
            if (verifySign && "SUCCESS".equals(map.get("result_code"))) { // 验签通过，交易成功，提取参数
                LocalDateTime parseTime = LocalDateTime.parse(map.get("time_end"), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
                // 更改支付状态
                payOrderService.update(new LambdaUpdateWrapper<PayOrder>()
                        .eq(PayOrder::getBuyerId, map.get("openid"))
                        .eq(PayOrder::getOutTradeNo, map.get("out_trade_no"))
                        .set(PayOrder::getTradeState, "SUCCESS")
                        .set(PayOrder::getTransactionId, map.get("transaction_id"))
                        .set(PayOrder::getPayEndTime, parseTime));
                // 业务逻辑操作
                JSONObject attach = JSONObject.parseObject(map.get("attach"));
                if ("COMBO".equals(attach.getString("type"))) {    // 源自充值套餐
                    comboOrderMapper.add(new ComboOrder(
                                    map.get("openid"),
                                    attach.getString("name"),
                                    parseTime,
                                    Float.parseFloat(map.get("total_fee")) / 100,
                                    attach.getFloat("amount"),
                                    parseTime.plusDays(attach.getInteger("days")),
                                    map.get("out_trade_no")
                            )
                    );
                    resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml>";
                } else {   // 源自查看 暂无操作(单次收费)
                    // 通知微信服务器已经支付成功
                    resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml>";
                }
            } else {
                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[校验失败]]></return_msg>" + "</xml>";
            }
        } else {
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[通信失败]]></return_msg>" + "</xml>";
        }
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        // 通知微信服务器处理结果
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }

}
